package com.zgw.fireline.base.widgets;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public abstract class TextPopup {
	protected Text text;
	private Shell shell;
	protected Control content;
	protected final Listener okListener;

	public TextPopup(final Text control, Listener selected) {
		this.okListener = selected;
		this.text = control;
		final Listener poupListener = new Listener() {
			public void handleEvent(Event event) {
				popupEvent(event);
			}
		};
		text.addListener(SWT.KeyDown, poupListener);
		text.addListener(SWT.Modify, poupListener);
		text.addListener(SWT.FocusOut, poupListener);
		text.addListener(SWT.MouseDown, poupListener);
		text.addListener(SWT.Verify, poupListener);
		text.getShell().addListener(SWT.Move, poupListener);
		text.getDisplay().addFilter(SWT.MouseDown, poupListener);
		text.addDisposeListener(new DisposeListener() {
			public void widgetDisposed(DisposeEvent e) {
				text.getDisplay().removeFilter(SWT.MouseDown, poupListener);
				text.getShell().removeListener(SWT.Move, poupListener);
				if (getShell() != null && !getShell().isDisposed()) {
					getShell().dispose();
				}
			}
		});
	}

	protected Shell getShell() {
		return shell;
	}

	boolean verify = false;

	void popupEvent(Event event) {
		if (SWT.Verify == event.type) {
			verify = event.character != 0;
		} else if (SWT.Modify == event.type && verify) {
			if (!isShow())
				show();
			doFilter(text.getText().trim());
		} else if (SWT.KeyDown == event.type && !isShow()) {
			if (event.keyCode == SWT.ARROW_DOWN
					|| event.character == SWT.KEYPAD_CR
					|| event.character == SWT.CR) {
				show(text.getText().trim());
			}
		} else if (SWT.KeyDown == event.type && isShow()) {
			if (event.character == SWT.KEYPAD_CR || event.character == SWT.CR) {
				okPressed();
				event.doit = false;
			} else if (event.keyCode == SWT.ESC) {
				hide();
			} else if (event.keyCode == SWT.ARROW_UP) {
				doSelectUp();
				event.doit = false;
			} else if (event.keyCode == SWT.ARROW_DOWN) {
				doSelectDown();
				event.doit = false;
			} else if (event.keyCode == SWT.BS) {// 退格
				if (text.getText().equals(""))
					hide();
			}
		} else if (SWT.MouseDown == event.type && isShow()) {
			if (shell.getDisplay().getActiveShell() != shell)
				hide();
		} else if (SWT.FocusOut == event.type && isShow()) {
			if (shell.getDisplay().getActiveShell() != shell)
				hide();
		} else if (SWT.Move == event.type && isShow()) {
			setRectangle();// 移动弹出框位置
		}
	}

	public boolean isShow() {
		return shell != null && !shell.isDisposed() && shell.isVisible();
	}

	protected void setRectangle() {
		if (shell != null && !shell.isDisposed()) {
			Point location = text.toDisplay(0, text.getSize().y);
			Point size = getSize();
			Rectangle rect = new Rectangle(location.x, location.y, size.x,
					size.y);
			shell.setBounds(rect);
		}
	}

	public void show() {
		show("");
	}

	public void show(String trim) {
		if (shell == null || shell.isDisposed()) {
			shell = new Shell(text.getShell(), SWT.NO_TRIM | SWT.NO_FOCUS
					| SWT.TOOL);
			shell.setLayout(new FillLayout());
			createContent(shell);
		}
		setRectangle();
		shell.setVisible(true);
		doFilter(trim);
	}

	public void hide() {
		if (isShow())
			shell.setVisible(false);
	}

	/**
	 * 选中确认
	 * */
	protected abstract void okPressed();

	/**
	 * 选中上一行记录
	 * */
	protected abstract void doSelectUp();

	/**
	 * 选中下一行记录
	 * */
	protected abstract void doSelectDown();

	/**
	 * 过滤条件发生改变
	 * */
	protected abstract void doFilter(String trim);

	protected abstract Control createContent(Composite parent);

	protected Point getSize() {
		return content.computeSize(SWT.DEFAULT, SWT.DEFAULT);
	}
}
